home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.cs.arizona.edu
/
ftp.cs.arizona.edu.tar
/
ftp.cs.arizona.edu
/
icon
/
newsgrp
/
group99a.txt
/
000191_icon-group-sender _Thu Sep 9 12:45:07 1999.msg
< prev
next >
Wrap
Internet Message Format
|
2000-09-20
|
5KB
Return-Path: <icon-group-sender>
Received: (from root@localhost)
by baskerville.CS.Arizona.EDU (8.9.1a/8.9.1) id MAA23587
for icon-group-addresses; Thu, 9 Sep 1999 12:43:22 -0700 (MST)
Message-Id: <199909091943.MAA23587@baskerville.CS.Arizona.EDU>
From: "Frank Lhota" <lhotaf@lexma.meitech.com>
To: <icon-group@optima.CS.Arizona.EDU>
Subject: Could we tend the result of memb?
Date: Thu, 9 Sep 1999 13:46:07 -0400
X-Priority: 3
X-MSMail-Priority: Normal
X-MimeOLE: Produced By Microsoft MimeOLE V5.00.2314.1300
Errors-To: icon-group-errors@optima.CS.Arizona.EDU
Status: RO
This message deals with the implementation of Icon, and assumes familiarity
with the current implementation.
Icon implements sets and tables using a hash chain system. The structures
for sets and tables are similar enough that they share a fair number of
common utilities. One of the most commonly used utilities for set and table
work is memb. The memb function determines whether a given item is a member
of a set or table. This function has the following prototype:
union block **memb (union block *pb,dptr x,uword hn, int *res);
The pb parameter is a pointer to either a set or table block. The x
parameter points to the descriptor of the value that memb will search for,
and hn is the hash value for *x. After calling memb, *res receives whether
*x cam be found in the set / table *pb (*res = 1 if the search succeeded, 0
otherwise). The result of memb is a pointer to a block pointer member within
some block that is part of the set / table representation. Assume we perform
int res;
union block **slot;
slot = memb(pb,x,hn,&res);
If *x was found in *pb (res == 1), *slot points to the set / table element
in *pd for *x. If *x was not found in *pb (res == 0), *slot is the location
that should receive the address of a newly created element for *x.
The handy, dandy memb function is useful for searching, modifying, adding
and deleting the elements of a set or table. There is one problem, however,
with memb: the result of memb cannot be tended. If a new block is allocated,
the existing blocks may get moved around, and a stored memb result will be
invalidated. Moreover, searches take a long time, so you really do not want
to repeat a search unless absolutely necessary. To avoid invalidating the
result of memb, several functions will perform an allocation before calling
memb, even if we need to see the results of memb to determine if the
allocation was actually needed. For example, the pseudo-code for inserting a
value X into a set S is basically this.
Allocate a new set element block;
Call memb to see if X is in S;
If ( X is not in S ) {
Fill in new set element block with data for X;
Link new set element block into S using result of memb;
}
else
Deallocate new set element block; /* it was not really needed */
This approach is complicated, error prone and inefficient. If there was only
some way to tend the result of memb, we could do the following more natural
and efficient algorithm:
Call memb to see if X is in S;
If ( X is not in S ) {
Allocate a new set element block;
Fill in new set element block with data for X;
Link new set element block into S using result of memb;
}
There is no known method for tending a value of type (union block **), since
one cannot reliably find the start of the block that this value points into.
Basically, memb is returning the address of a member in some block. Could
memb return this information in another form that can be tended?
One possibility that comes to mind is that memb can return its result in a
tended variable of type struct descrip. Remember, the result is always an
address of a member of some block. We can store the start of this block in
the BlkLoc part of the descriptor. The offset from the start of the block to
the particular member can be stored in the Offset portion of the dword
member of the descriptor. The resulting descriptor is in a form quite
similar to descriptors that are currently tended. Consider an alternative
form of memb:
int memb (union block *pb,dptr x,uword hn, dptr slot);
In this new version, the function return value indicates whether the search
was successful (1 if search succeeded, 0 if failed). The slot parameter is
the address of a tended descriptor. Upon return, we have:
slot.dword = (F_Nqual | F_Ptr) | ( offset in words to the member )
BlkLoc(*s) = (Start of the block)
If we do this, should also add a macro that will turn such a descriptor into
a (union block **) value.
Before I start working on this, I pose this question: does anyone know of a
reason why this wouldn't work, or wouldn't be desirable?